﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace FerrSimplicity
{
    /// <summary>
    /// Creates random values in an array of different manners. Also only utilizes one 
    /// random class, so there are no worries about creating more than one Random class
    /// during the same millisecond. Also provides a way to create random numbers specifically 
    /// from a given seed.
    /// </summary>
    public static class UtilRandom
    {
        public static Random random = new Random();
        public static float   CreateFloat     (float   aMin, float   aMax)
        {
            return (aMin + ((float)random.NextDouble() * (aMax - aMin)));
        }
        public static int     CreateInt       (int     aMin, int     aMax)
        {
            return (random.Next(aMin, aMax));
        }
        public static Vector3 CreateVectorBox (Vector3 aMin, Vector3 aMax)
        {
            return new Vector3(CreateFloat(aMin.X, aMax.X), CreateFloat(aMin.Y, aMax.Y), CreateFloat(aMin.Z, aMax.Z));
        }
        public static Vector3 CreateVectorLerp(Vector3 aMin, Vector3 aMax)
        {
            return Vector3.Lerp(aMin, aMax, CreateFloat(0, 1));
        }
        public static Vector2 CreateDirection (float aMinAng, float aMaxAng, float aMinLength, float aMaxLength)
        {
            float ang    = CreateFloat(aMinAng,    aMaxAng   );
            float length = CreateFloat(aMinLength, aMaxLength);

            return new Vector2((float)Math.Cos(ang) * length, (float)Math.Sin(ang) * length);
        }
        public static Vector2 CreatePoint     (Rectangle aRect)
        {
            return new Vector2(CreateFloat(aRect.Left, aRect.Right), CreateFloat(aRect.Top, aRect.Bottom));
        }
        public static Vector2 CreatePoint     (Vector2   aMax )
        {
            return new Vector2(CreateFloat(0, aMax.X), CreateFloat(0, aMax.Y));
        }

        private static float Rand(int aSeed)
        {
            int n = aSeed;
            n = (n << 13) ^ n;
            return (((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f) / 2f;
        }
        public static float   CreateFloat     (int aSeed, float   aMin, float   aMax)
        {
            return (aMin + ((float)Rand(aSeed) * (aMax - aMin)));
        }
        public static int     CreateInt       (int aSeed, int     aMin, int     aMax)
        {
            return (int)(aMin + (Rand(aSeed) * (aMax - aMin)));
        }
        public static Vector3 CreateVectorBox (int aSeed, Vector3 aMin, Vector3 aMax)
        {
            return new Vector3((aMin.X + ((float)Rand(aSeed) * (aMax.X - aMin.X))),
                               (aMin.Y + ((float)Rand(aSeed) * (aMax.Y - aMin.Y))),
                               (aMin.Z + ((float)Rand(aSeed) * (aMax.Z - aMin.Z))));
        }
        public static Vector3 CreateVectorLerp(int aSeed, Vector3 aMin, Vector3 aMax)
        {
            return Vector3.Lerp(aMin, aMax, Rand(aSeed));
        }
        public static Vector2 CreateDirection (int aSeed, float aMinAng, float aMaxAng, float aMinLength, float aMaxLength)
        {
            float ang    = (aMinAng    + ((float)Rand(aSeed) * (aMaxAng    - aMinAng)));
            float length = (aMinLength + ((float)Rand(aSeed) * (aMaxLength - aMinLength)));

            return new Vector2((float)Math.Cos(ang) * length, (float)Math.Sin(ang) * length);
        }
        public static Vector2 CreatePoint     (int aSeed, Rectangle aRect)
        {
            return new Vector2((aRect.Left + (Rand(aSeed) * (aRect.Right  - aRect.Left))),
                               (aRect.Top  + (Rand(aSeed) * (aRect.Bottom - aRect.Top ))));
        }
        public static Vector2 CreatePoint     (int aSeed, Vector2   aMax )
        {
            return new Vector2(Rand(aSeed) * aMax.X, Rand(aSeed) * aMax.Y);
        }
    }
}
